package com.zhou.JavaAndroidFirm.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.Nullable;
import android.text.Html;
import android.text.Layout;
import android.text.Selection;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.text.method.Touch;
import android.text.style.ClickableSpan;
import android.text.style.ImageSpan;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition;
import com.zhou.JavaAndroidFirm.R;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

/**
 * 加载html格式包含多张图片
 * Created by Huang Mingfei on 2017/12/6 0006.
 * 富文本显示TextView
 */
public class RichText extends TextView {
    private Drawable placeHolder, errorImage;//占位图，错误图
    private OnImageClickListener onImageClickListener;//图片点击回调
    private HashSet<Target> targets;
    private int maxWidth;
    private String mContent;


    public RichText(Context context) {
        this(context, null);
    }

    public RichText(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RichText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        targets = new HashSet<>();
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RichText);
        placeHolder = typedArray.getDrawable(R.styleable.RichText_placeHolder);
        errorImage = typedArray.getDrawable(R.styleable.RichText_errorImage);

        if (placeHolder == null) {
            placeHolder = getContext().getResources().getDrawable(R.drawable.ic_image_loading);
        }
        if (errorImage == null) {
            errorImage = getContext().getResources().getDrawable(R.drawable.ic_empty_picture);
        }
        typedArray.recycle();
    }


    /**
     * 设置富文本
     *
     * @param text 富文本
     */
    public void setRichText(String text) {
        if (null == text) {
            mContent = "";
        } else {
            mContent = text;
        }
        targets.clear();
        getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                maxWidth = RichText.this.getWidth() - RichText.this.getCompoundPaddingLeft() - RichText.this.getCompoundPaddingRight();
                if (Build.VERSION.SDK_INT < 16) {
                    getViewTreeObserver().removeGlobalOnLayoutListener(this);
                } else {
                    getViewTreeObserver().removeOnGlobalLayoutListener(this);
                }
                Spanned spanned = Html.fromHtml(mContent, asyncImageGetter, null);
                SpannableStringBuilder spannableStringBuilder;
                if (spanned instanceof SpannableStringBuilder) {
                    spannableStringBuilder = (SpannableStringBuilder) spanned;
                } else {
                    spannableStringBuilder = new SpannableStringBuilder(spanned);
                }

                ImageSpan[] imageSpans = spannableStringBuilder.getSpans(0, spannableStringBuilder.length(), ImageSpan.class);
                final List<String> imageUrls = new ArrayList<>();

                for (int i = 0, size = imageSpans.length; i < size; i++) {
                    ImageSpan imageSpan = imageSpans[i];
                    String imageUrl = imageSpan.getSource();
                    int start = spannableStringBuilder.getSpanStart(imageSpan);
                    int end = spannableStringBuilder.getSpanEnd(imageSpan);
                    imageUrls.add(imageUrl);

                    final int finalI = i;
                    ClickableSpan clickableSpan = new ClickableSpan() {
                        @Override
                        public void onClick(View widget) {
                            if (onImageClickListener != null) {
                                onImageClickListener.imageClicked(imageUrls, finalI);
                            }
                        }
                    };
                    ClickableSpan[] clickableSpans = spannableStringBuilder.getSpans(start, end, ClickableSpan.class);
                    if (clickableSpans != null && clickableSpans.length != 0) {
                        for (ClickableSpan cs : clickableSpans) {
                            spannableStringBuilder.removeSpan(cs);
                        }
                    }
                    spannableStringBuilder.setSpan(clickableSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                }
                RichText.super.setText(spanned);
                setMovementMethod(LinkMovementMethod.getInstance());

            }
        });

    }


    /**
     * 异步加载图片（依赖于Glide）
     */
    private Html.ImageGetter asyncImageGetter = new Html.ImageGetter() {
        @Override
        public Drawable getDrawable(String source) {
            final URLDrawable urlDrawable = new URLDrawable();
            SimpleTarget target = new SimpleTarget<Bitmap>() {
                @Override
                public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) {
                    float rate = resource.getWidth() == 0 ? 1f : (float) resource.getHeight() / (float) resource.getWidth();
                    Drawable drawable = new BitmapDrawable(getContext().getResources(), resource);
                    drawable.setBounds(0, 0, maxWidth, (int) (maxWidth * rate));
                    urlDrawable.setBounds(drawable.getBounds());
                    urlDrawable.setDrawable(drawable);
                }

                @Override
                public void onLoadFailed(@Nullable Drawable errorDrawable) {
                    errorImage.setBounds(0, 0, maxWidth, maxWidth / 2);
                    urlDrawable.setBounds(errorImage.getBounds());
                    urlDrawable.setDrawable(errorImage);
                }

                @Override
                public void onLoadStarted(@Nullable Drawable placeholder) {
                    placeHolder.setBounds(0, 0, maxWidth, maxWidth / 2);
                    urlDrawable.setBounds(placeHolder.getBounds());
                    urlDrawable.setDrawable(placeHolder);
                }
            };
            targets.add(target);
            Glide.with(getContext()).asBitmap().load(source).into(target);
            return urlDrawable;
        }
    };


    private static final class URLDrawable extends BitmapDrawable {
        private Drawable drawable;

        @SuppressWarnings("deprecation")
        public URLDrawable() {
        }

        @Override
        public void draw(Canvas canvas) {
            if (drawable != null) {
                drawable.draw(canvas);
            }
        }

        public void setDrawable(Drawable drawable) {
            this.drawable = drawable;
        }
    }


    public void setOnImageClickListener(OnImageClickListener onImageClickListener) {
        this.onImageClickListener = onImageClickListener;
    }

    public interface OnImageClickListener {
        /**
         * 图片被点击后的回调方法
         *
         * @param imageUrls 本篇富文本内容里的全部图片
         * @param position  点击处图片在imageUrls中的位置
         */
        void imageClicked(List<String> imageUrls, int position);
    }

    /********************可以响应内部点击事件，但是父布局的点击事件会被消费掉**************************/
    public boolean linkHit;//内部链接是否被点击

    @Override
    public boolean performClick() {
        if (linkHit) {
            return true;
        }
        return super.performClick();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        linkHit = false;
        return super.onTouchEvent(event);
    }

    public static class CustomLinkMovementMethod extends LinkMovementMethod {

        static CustomLinkMovementMethod sInstance;

        @Override
        public boolean onTouchEvent(TextView widget, Spannable buffer,
                                    MotionEvent event) {
            int action = event.getAction();

            if (action == MotionEvent.ACTION_UP ||
                    action == MotionEvent.ACTION_DOWN) {
                int x = (int) event.getX();
                int y = (int) event.getY();

                x -= widget.getTotalPaddingLeft();
                y -= widget.getTotalPaddingTop();

                x += widget.getScrollX();
                y += widget.getScrollY();

                Layout layout = widget.getLayout();
                int line = layout.getLineForVertical(y);
                int off = layout.getOffsetForHorizontal(line, x);

                ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);

                if (link.length != 0) {
                    if (action == MotionEvent.ACTION_UP) {
                        link[0].onClick(widget);

                    } else if (action == MotionEvent.ACTION_DOWN) {
                        Selection.setSelection(buffer,
                                buffer.getSpanStart(link[0]),
                                buffer.getSpanEnd(link[0]));
                    }

                    if (widget instanceof RichText) {
                        ((RichText) widget).linkHit = true;
                    }

                    return true;
                } else {
                    Selection.removeSelection(buffer);
                    super.onTouchEvent(widget, buffer, event);
                    return false;
                }
            }

            return Touch.onTouchEvent(widget, buffer, event);
        }

        public static CustomLinkMovementMethod getInstance() {
            if (sInstance == null) {
                sInstance = new CustomLinkMovementMethod();
            }
            return sInstance;
        }
    }

    /********************不可以响应内部点击事件，但是点击事件没有异常**************************/
//    boolean dontConsumeNonUrlClicks = true;
//
//    boolean linkHit;
//
//
//    @Override
//    public boolean onTouchEvent(MotionEvent event) {
//        linkHit = false;
//        boolean res = super.onTouchEvent(event);
//        if (dontConsumeNonUrlClicks) {
//            return linkHit;
//        }
//        return res;
//    }
//
//    @Override
//    public boolean hasFocusable() {
//        return false;
//    }
//
//    public static class LocalLinkMovementMethod extends LinkMovementMethod {
//        static LocalLinkMovementMethod sInstance;
//
//        public static LocalLinkMovementMethod getInstance() {
//            if (sInstance == null) {
//                sInstance = new LocalLinkMovementMethod();
//            }
//            return sInstance;
//        }
//
//        @Override
//        public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
//            int action = event.getAction();
//            if (action == MotionEvent.ACTION_UP ||
//                    action == MotionEvent.ACTION_DOWN) {
//                int x = (int) event.getX();
//                int y = (int) event.getY();
//                x -= widget.getTotalPaddingLeft();
//                y -= widget.getTotalPaddingTop();
//
//                x += widget.getScrollX();
//                y += widget.getScrollY();
//
//                Layout layout = widget.getLayout();
//                int line = layout.getLineForVertical(y);
//                int off = layout.getOffsetForHorizontal(line, x);
//
//                ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
//
//                if (link.length != 0) {
//                    if (action == MotionEvent.ACTION_UP) {
//                        link[0].onClick(widget);
//                    } else if (action == MotionEvent.ACTION_DOWN) {
//                        Selection.setSelection(buffer,
//                                buffer.getSpanStart(link[0]),
//                                buffer.getSpanEnd(link[0]));
//                    }
////                    if (widget instanceof RichText) {
////                        ((RichText) widget).linkHit = true;
////                    }
//                    return true;
//                } else {
//                    Selection.removeSelection(buffer);
//                    Touch.onTouchEvent(widget, buffer, event);
//                    return false;
//                }
//            }
//            //http://my.oschina.net/djone/blog/145057
//            return Touch.onTouchEvent(widget, buffer, event);
//        }
//    }


}